#pragma once
#ifndef WORLD_H
#define WORLD_H
#include <ctime>
#include <vector>
#include <list>
#include <limits>
#include <iostream>
#include "AVector.h"
#include "mapNode.h"
//#include "triangleAgent.h"
//#include "agent.h"
#include "squad.h"
#include "structure.h"
#include "resource.h"
#include "Terrain.h"

using namespace std;


#define SEPERATIONRANGE 50
#define COHESIONRANGE 100
#define ALIGNMENTRANGE 100
#define BORDERRANGE 1
#define OBSTACLERANGE 2.5  //This is a percentage multiplied against obstacle radius
#define GOALRANGE 200
#define SPEEDLIMIT .16

#define SEPMODIFIER 0.01
#define COHMODIFIER 0.0001
#define ALIMODIFIER 0.003
#define BORDERMODIFIER 0.00001
#define OBSTACLEMODIFIER 0.01
#define GOALMODIFIER .000001

// A* HEURISTIC MODIFIER
#define HEURISTICMOD 25

#define TRI_DIRT_LIMIT    0.1/3.0
#define CIRC_DIRT_LIMIT   0.08/3.0
#define RECT_DIRT_LIMIT   0.1/3.0
#define TRI_ROAD_LIMIT    2/3.0
#define CIRC_ROAD_LIMIT   2/3.0
#define RECT_ROAD_LIMIT   0.75
#define TRI_GRAVEL_LIMIT  0.02
#define CIRC_GRAVEL_LIMIT 0.01
#define RECT_GRAVEL_LIMIT 0.01/2.0

#define RESOURCE_SPAWN_DELAY 1000
#define RESOURCE_MAX_COUNT 5
#define RESOURCE_PICKUP_RADIUS 5
#define RESOURCE_PLAYER_MAX 9999

//Population
#define POP_HARDCAP 200
#define SUPPLYAMMOUNT 10

class H_Compare {
    public:
    bool operator()(mapNode* m1, mapNode* m2) 
    {
		return m2->fScore < m1->fScore;
    }

};

class world
{
public:
	world(void);
	~world(void);

	bool goalActive;                                    //TODO: Remove
	vertex goal;                                        //TODO: Remove

	Terrain map;

	// Population variables
	int bluePopulation, redPopulation;
	int blueSupplies, redSupplies;

	//Squadlist
	//int maxSquads;
	vector<squad *> squadList;

	//structureList
	int structureMax;
	//int structureCount;
	bool structures_changed;
	vector<structure *> structureList;

	// Private variable functions
	//int getSquadCount(void);
	//squad * fetchSquad(int);
	int addSquad(squad *);
	//int getStructureCount(void);
	//structure * fetchStructure(int);
	int addStructure(structure *);
	void resetSquads(void);
	void resetStructures(void);

	void updateSquadAgents(int, time_t, FILE *);

	// Agents Forces
	AVector seperationForce(squad *, int);
	AVector agentAvoidForce(squad *, int, int);
	AVector cohesionForce(squad *,int);
	AVector alignmentForce(squad *,int);
	AVector borderForce(squad *,int, float, float, float, float);
	AVector obstacleForce(squad *,int);
	AVector goalForce(squad *,int);
	AVector targetForce(squad *,agent *);
	void limitSpeed(squad *, agent *);

	// A* related functions & variables
	float triGravelCost, triDirtCost, triRoadCost;
	float rectGravelCost, rectDirtCost, rectRoadCost;
	float circGravelCost, circDirtCost, circRoadCost;
	bool inList(vector<mapNode*> *, mapNode*);
	float costBetween(shape_T,mapNode*,mapNode*);
	list<vertex> AStarPlan(squad *, vertex);

	// Resource related functions and variables
	int player_resources;
	float resource_spawn_counter;
	vector<resource> resourceList;
	void spawnResources(float);
	bool attemptResourcePickup(vertex, team_T);

	// destroyed objects list
	vector<void*> destroyList;
	int destroyCleanup( FILE *);


private:

	//int agentCount, agentMax;
	//agent * agentList[30];

	//int squadCount, squadMax;
	//squad * squadList[30];

	//vector<structure *> structureList;
};
#endif
